#include "mqtt_comm.h"
#include "cJSON.h"
#include <mosquitto.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* 定义全局变量：接收数据与发送数据 */
RobotControlData g_robotControlData = {.client_id = "",
                                       .msg_id = "",
                                       .move_type = "",
                                       .parameter = 0,
                                       .axis_num = 0};

RobotStateData g_robotStateData = {
    .status = 0,    // 0:运行中
    .parameter = 0, // 当前位置
    .axis_num = 29  // 默认轴号29
};

/* 全局标志位：初始为false */
volatile bool g_new_message_flag = false;

/* MQTT 相关参数 */
static struct mosquitto *mosq = NULL;
static const char *sub_topic = "AxisControl/MainAxisGroup"; // 接收话题
static const char *pub_status_topic = "AxisStatus/MainAxisGroup"; // 状态话题
static char pub_ack_topic[256] = ""; // 应答话题（动态生成）
/* 全局控制话题 */
static const char *global_halt_topic = "GlobalControl/Halt";
static const char *global_disable_topic = "GlobalControl/DisableVoltage";
/* 发送线程句柄 */
static pthread_t send_thread;

/* 内部函数声明 */
static void on_connect(struct mosquitto *mosq, void *obj, int rc);
static void on_message(struct mosquitto *mosq, void *obj,
                       const struct mosquitto_message *msg);
static void *send_thread_func(void *arg);

/**
 * @brief 初始化 MQTT 客户端、建立连接并启动后台线程
 */
int mqtt_comm_init(const char *broker_address, int broker_port) {
  int ret;
  mosquitto_lib_init();
  mosq = mosquitto_new(NULL, true, NULL);
  if (!mosq) {
    fprintf(stderr, "创建 mosquitto 客户端失败\n");
    return -1;
  }

  /* 设置回调函数 */
  mosquitto_connect_callback_set(mosq, on_connect);
  mosquitto_message_callback_set(mosq, on_message);

  ret = mosquitto_connect(mosq, broker_address, broker_port, 60);
  if (ret) {
    fprintf(stderr, "连接失败, 错误码：%d\n", ret);
    return ret;
  }

  /* 启动网络处理线程 */
  ret = mosquitto_loop_start(mosq);
  if (ret) {
    fprintf(stderr, "启动 mosquitto 网络循环失败：%d\n", ret);
    return ret;
  }

  /* 创建发送线程，每秒发布一次状态数据 */
  ret = pthread_create(&send_thread, NULL, send_thread_func, NULL);
  if (ret) {
    fprintf(stderr, "创建发送线程失败\n");
    return ret;
  }

  return 0;
}

/**
 * @brief 清理 MQTT 客户端资源
 */
void mqtt_comm_cleanup(void) {
  if (mosq) {
    mosquitto_disconnect(mosq);
    mosquitto_loop_stop(mosq, true);
    mosquitto_destroy(mosq);
  }
  mosquitto_lib_cleanup();
}

/**
 * @brief 启动通讯任务
 */
void mqtt_comm_start(void) { pthread_detach(send_thread); }

/**
 * @brief MQTT 连接成功后的回调函数
 */
static void on_connect(struct mosquitto *mosq, void *obj, int rc) {
  if (rc == 0) {
    printf("成功连接到 MQTT 服务器。\n");
    mosquitto_subscribe(mosq, NULL, sub_topic, 0);
    printf("订阅话题: %s\n", sub_topic);
    /*订阅全局控制话题*/
    mosquitto_subscribe(mosq, NULL, global_halt_topic, 0);
    mosquitto_subscribe(mosq, NULL, global_disable_topic, 0);
    printf("已订阅全局话题: %s 和 %s\n", global_halt_topic,
           global_disable_topic);
  } else {
    printf("连接失败，错误码：%d\n", rc);
  }
}

/**
 * @brief 收到消息后的回调函数
 *
 * 解析JSON格式:
 * {
 *   "client_id": "jitri",
 *   "msg_id": "20250827-0001",
 *   "move_type": "absolute",
 *   "parameter": [100],
 *   "option": {
 *     "axis_num": 29
 *   }
 * }
 */
static void on_message(struct mosquitto *mosq, void *obj,
                       const struct mosquitto_message *msg) {
  (void)obj;

  /* +++ 新增：首先处理全局非JSON话题 +++ */
  // 这些话题不需要解析JSON，可以直接处理
  if (strcmp(msg->topic, global_halt_topic) == 0) {
    printf("收到全局暂停命令 (GlobalControl/Halt)\n");

    // 模拟一个 "halt" JSON 消息，以触发 term.c 中的逻辑
    strncpy(g_robotControlData.move_type, "halt",
            sizeof(g_robotControlData.move_type) - 1);
    g_robotControlData.axis_num = 29; // 确保 term.c 会处理它
    // 清空 msg_id 和 client_id，因为这是特殊命令
    memset(g_robotControlData.msg_id, 0, sizeof(g_robotControlData.msg_id));
    memset(g_robotControlData.client_id, 0,
           sizeof(g_robotControlData.client_id));
    g_robotControlData.parameter = 0;

    g_new_message_flag = true; // 触发 term.c 处理
    return;                    // 处理完毕
  } else if (strcmp(msg->topic, global_disable_topic) == 0) {
    printf("收到全局停机命令 (GlobalControl/DisableVoltage)\n");

    // 模拟一个 "disable_voltage" JSON 消息
    strncpy(g_robotControlData.move_type, "disable_voltage",
            sizeof(g_robotControlData.move_type) - 1);
    g_robotControlData.axis_num = 29; // 确保 term.c 会处理它
    // 清空 msg_id 和 client_id
    memset(g_robotControlData.msg_id, 0, sizeof(g_robotControlData.msg_id));
    memset(g_robotControlData.client_id, 0,
           sizeof(g_robotControlData.client_id));
    g_robotControlData.parameter = 0;

    g_new_message_flag = true; // 触发 term.c 处理
    return;                    // 处理完毕
  }
  /* --- 全局话题处理结束 --- */

  if (msg->payloadlen && strcmp(msg->topic, sub_topic) == 0) {
    printf("收到消息，话题: %s\n", msg->topic);
    printf("消息内容: %s\n", (char *)msg->payload);

    cJSON *root = cJSON_Parse(msg->payload);
    if (root == NULL) {
      fprintf(stderr, "JSON解析失败\n");
      return;
    }

    /* 解析 client_id */
    cJSON *client_id = cJSON_GetObjectItem(root, "client_id");
    if (cJSON_IsString(client_id)) {
      strncpy(g_robotControlData.client_id, client_id->valuestring,
              sizeof(g_robotControlData.client_id) - 1);

      /* 动态生成应答话题: AxisControlAck/{client_id}/MainAxisGroup */
      snprintf(pub_ack_topic, sizeof(pub_ack_topic),
               "AxisControlAck/%s/MainAxisGroup", client_id->valuestring);
      printf("应答话题设置为: %s\n", pub_ack_topic);
    }

    /* 解析 msg_id */
    cJSON *msg_id = cJSON_GetObjectItem(root, "msg_id");
    if (cJSON_IsString(msg_id)) {
      strncpy(g_robotControlData.msg_id, msg_id->valuestring,
              sizeof(g_robotControlData.msg_id) - 1);
    }

    /* 解析 move_type */
    cJSON *move_type = cJSON_GetObjectItem(root, "move_type");
    if (cJSON_IsString(move_type)) {
      strncpy(g_robotControlData.move_type, move_type->valuestring,
              sizeof(g_robotControlData.move_type) - 1);
    }

    /* 解析 parameter 数组 */
    cJSON *parameter = cJSON_GetObjectItem(root, "parameter");
    if (cJSON_IsArray(parameter) && cJSON_GetArraySize(parameter) > 0) {
      cJSON *param0 = cJSON_GetArrayItem(parameter, 0);
      if (cJSON_IsNumber(param0)) {
        g_robotControlData.parameter = param0->valuedouble;
      }
    }

    /* 解析 option.axis_num */
    cJSON *option = cJSON_GetObjectItem(root, "option");
    if (option && cJSON_IsObject(option)) {
      cJSON *axis_num = cJSON_GetObjectItem(option, "axis_num");
      if (cJSON_IsNumber(axis_num)) {
        g_robotControlData.axis_num = axis_num->valueint;
        // g_robotStateData.axis_num = axis_num->valueint; // 同步更新状态
      }
    }

    // 打印接收到的数据
    printf("接收到控制数据:\n");
    printf("  client_id: %s\n", g_robotControlData.client_id);
    printf("  msg_id: %s\n", g_robotControlData.msg_id);
    printf("  move_type: %s\n", g_robotControlData.move_type);
    printf("  parameter: %f\n", g_robotControlData.parameter);
    printf("  axis_num: %d\n", g_robotControlData.axis_num);

    g_new_message_flag = true;

    cJSON_Delete(root);
  }
}

/**
 * @brief 发送应答消息
 *
 * 发送到话题: AxisControlAck/{client_id}/MainAxisGroup
 * JSON格式:
 * {
 *   "msg_id": "20250827-0001",
 *   "status": 1
 * }
 */
void mqtt_send_ack(const char *msg_id, int status) {
  if (strlen(pub_ack_topic) == 0) {
    fprintf(stderr, "应答话题未设置，无法发送应答\n");
    return;
  }

  cJSON *root = cJSON_CreateObject();
  if (!root) {
    fprintf(stderr, "创建应答 JSON 对象失败\n");
    return;
  }

  cJSON_AddStringToObject(root, "msg_id", msg_id);
  cJSON_AddNumberToObject(root, "status", status);

  char *json_str = cJSON_PrintUnformatted(root);
  if (json_str) {
    printf("发送应答到 %s: %s\n", pub_ack_topic, json_str);
    int ret = mosquitto_publish(mosq, NULL, pub_ack_topic,
                                (int)strlen(json_str), json_str, 0, false);
    if (ret != MOSQ_ERR_SUCCESS) {
      fprintf(stderr, "发布应答消息失败: %s\n", mosquitto_strerror(ret));
    }
    free(json_str);
  }

  cJSON_Delete(root);
}

/**
 * @brief 发送线程函数
 *
 * 每隔1秒发送实时状态到话题: AxisStatus/MainAxisGroup
 * JSON格式:
 * {
 *   "status": 1,
 *   "parameter": [100],
 *   "option": {
 *     "axis_num": 29
 *   }
 * }
 */
static void *send_thread_func(void *arg) {
  (void)arg;

  while (1) {
    cJSON *root = cJSON_CreateObject();
    if (!root) {
      fprintf(stderr, "创建状态 JSON 对象失败\n");
      sleep(1);
      continue;
    }

    /* 添加 status */
    cJSON_AddNumberToObject(root, "status", g_robotStateData.status);

    /* 添加 parameter 数组 */
    cJSON *parameter = cJSON_CreateArray();
    cJSON_AddItemToArray(parameter,
                         cJSON_CreateNumber(g_robotStateData.parameter));
    cJSON_AddItemToObject(root, "parameter", parameter);

    /* 添加 option 对象 */
    cJSON *option = cJSON_CreateObject();
    cJSON_AddNumberToObject(option, "axis_num", g_robotStateData.axis_num);
    cJSON_AddItemToObject(root, "option", option);

    char *json_str = cJSON_PrintUnformatted(root);
    if (json_str) {
      printf("发送状态到 %s: %s\n", pub_status_topic, json_str);
      int ret = mosquitto_publish(mosq, NULL, pub_status_topic,
                                  (int)strlen(json_str), json_str, 0, false);
      if (ret != MOSQ_ERR_SUCCESS) {
        fprintf(stderr, "发布状态消息失败: %s\n", mosquitto_strerror(ret));
      }
      free(json_str);
    }

    cJSON_Delete(root);
    usleep(100000);
  }

  return NULL;
}